package com.wh1200.mybatis.xmlless.plugin.visitor

import com.wh1200.mybatis.xmlless.util.TypeUtil
import com.wh1200.mybatis.xmlless.util.getXmllessTableInfo
import net.sf.jsqlparser.schema.Table
import net.sf.jsqlparser.statement.StatementVisitorAdapter
import net.sf.jsqlparser.statement.delete.Delete
import net.sf.jsqlparser.statement.select.PlainSelect
import net.sf.jsqlparser.statement.select.Select
import net.sf.jsqlparser.statement.update.Update

class SelectVisitor : StatementVisitorAdapter(), BaseSelectVisitor {

  private val tables: MutableMap<String, Class<*>> = mutableMapOf()

  override fun visit(delete: Delete) {
    if (delete.table != null) {
      processTable(delete.table)
    }
    val fromVisitor = FromVisitor()
    delete.joins?.forEach {
      it.rightItem.accept(fromVisitor)
    }
    tables.putAll(fromVisitor.getTables())
    delete.where?.accept(ReplaceExpressionVisitor(tables))
  }

  override fun visit(update: Update) {
    if (update.table != null) {
      processTable(update.table)
    }
    val fromVisitor = processFromItem(update.fromItem)
    update.joins?.forEach {
      it.rightItem.accept(fromVisitor)
    }
    tables.putAll(fromVisitor.getTables())
    update.where?.accept(ReplaceExpressionVisitor(tables))
    update.updateSets.forEach {
      it.columns.forEach { column ->
        column.accept(ReplaceExpressionVisitor(tables))
      }
    }
  }

  private fun processTable(table: Table) {
    val modelClass = TypeUtil.resolve<Any>(table.name)
    val tableInfo = getXmllessTableInfo(modelClass)
    if (table.alias != null) {
      tables[table.alias.name] = modelClass
    } else {
      tables[""] = modelClass
    }
    table.name = tableInfo.tableName
  }

  override fun visit(select: Select) {
    val selectBody = select.selectBody as PlainSelect
    processSelectBody(selectBody)
  }


  override fun getTables(): MutableMap<String, Class<*>> {
    return tables
  }

}
